package com.study.stream;

import com.study.lambda.Employee;
import org.junit.Test;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 终止操作
 * */
public class TestStream3 {
    List<Employee> emp= Arrays.asList(
            new Employee(101,"张三",18,9999.99, Employee.Status.FREE),
            new Employee(102,"李四",59,6666.66, Employee.Status.BUSY),
            new Employee(103,"王五",27,3333.33, Employee.Status.VOCATION),
            new Employee(104,"赵六",8,7777.77, Employee.Status.FREE),
            new Employee(105,"田七",38,5555.55, Employee.Status.BUSY)
    );

    /**
     * 查找与匹配
     * allMatch——检查是否匹配所有元素
     * anyMatch——检查是否至少匹配一个元素
     * noneMatch——检查是否没有匹配全部元素
     * findFirst——返回第一个元素
     * findAny——返回当前流中任意元素
     * count——返回流中元素的总个数
     * max——返回流中最大值
     * min——返回流中最小值
     * */
    @Test
    public void test1(){
        boolean b = emp.stream().allMatch((str) -> str.getStatus().equals(Employee.Status.BUSY));
        System.out.println("allmatch:"+b);
        boolean b1 = emp.stream().anyMatch((str) -> str.getStatus().equals(Employee.Status.BUSY));
        System.out.println("anyMathc:"+b1);
        boolean b2 = emp.stream().noneMatch((str) -> str.getStatus().equals(Employee.Status.BUSY));
        System.out.println("noneMatch:"+b2);
        Optional<Employee> first = emp.stream().filter((str) -> str.getStatus().equals(Employee.Status.BUSY)).findFirst();
        System.out.println("findFirst:"+first.get());
        Optional<Employee> any = emp.parallelStream().filter((str) -> str.getStatus().equals(Employee.Status.BUSY)).findAny();
        System.out.println("findAny:"+any.get());
        Long count=emp.stream().count();
        System.out.println("count:"+count);
        Optional<Employee> max = emp.stream().max((t1, t2) -> Double.compare(t1.getScore(), t2.getScore()));
        System.out.println("max:"+max.get());
        Optional<Integer> min = emp.stream().map((str) -> str.getAge()).min(Integer::compare);
        System.out.println("min:"+min.get());
    }
    
    /**
     * 归约
     * reduce
     * reduce(T identity,BinaryOperator)/reduce(BinaryOperator)——可以将流中元素反复集合起来得到一个值
     * */
    @Test
    public void test2(){
        List<Integer> list=Arrays.asList(1,2,3,4,5,6,7,8,9,10);
        Integer reduce = list.stream().reduce(0, (x, y) -> x + y);
        System.out.println("reduce:"+reduce);
        System.out.println("-----------------------------------------");
        Optional<Double> reduce1 = emp.stream().map(Employee::getScore).reduce(Double::sum);
        System.out.println("reduce:"+reduce1.get());

    }

    /**
     * Collect收集器
     * */
    @Test
    public void test3(){
        List<String> collect = emp.stream()
                .map(Employee::getName)
                .collect(Collectors.toList());
        collect.forEach(System.out::println);
        System.out.println("--------------------------");
        Map<String, Integer> collect1 = emp.stream()
                .collect(Collectors.toMap(Employee::getName, Employee::getAge));
        collect1.forEach((k,v)-> System.out.println("key:"+ k+",value:"+v));
        System.out.println("--------------------------");
        Set<String> collect2 = emp.stream()
                .map(Employee::getName)
                .collect(Collectors.toSet());
        collect2.forEach(System.out::println);
        System.out.println("--------------------------");
        HashSet<Employee> collect3 = emp.stream()
                .collect(Collectors.toCollection(HashSet::new));
        collect3.forEach(System.out::println);
    }

    @Test
    public void test4(){
        //求总和
        Long collect = emp.stream()
                .collect(Collectors.counting());
        System.out.println("count:"+collect);
        //求平均值
        Double collect1 = emp.stream()
                .map(Employee::getScore)
                .collect(Collectors.averagingDouble(x->x));
        System.out.println("avg:"+collect1);
        //求和
        Double collect2 = emp.stream()
                .map(Employee::getScore)
                .collect(Collectors.summingDouble(x -> x));
        System.out.println("sum:"+collect2);
        //求最大值
        Optional<Integer> collect3 = emp.stream()
                .map(Employee::getAge)
                .collect(Collectors.maxBy(Integer::compare));
        System.out.println("max:"+collect3.get());
        //求最小值
        Optional<Double> collect4 = emp.stream()
                .map(Employee::getScore)
                .collect(Collectors.minBy(Double::compareTo));
        System.out.println("min:"+collect4.get());
        //值集合
        DoubleSummaryStatistics collect5 = emp.stream()
                .map(Employee::getScore)
                .collect(Collectors.summarizingDouble(x -> x));
        System.out.println("collect5:sum:"+collect5.getSum());
        System.out.println("collect5:average:"+collect5.getAverage());
        System.out.println("collect5:max:"+collect5.getMax());
        System.out.println("collect5:count:"+collect5.getCount());
        System.out.println("collect5:min:"+collect5.getMin());
    }

    @Test
    public void test5(){
        //分组
        Map<Employee.Status, List<Employee>> collect = emp.stream()
                .collect(Collectors.groupingBy((x) -> x.getStatus()));
        collect.forEach((k,v)->{
            System.out.println("key:"+k);
            v.forEach(System.out::println);
        });
        System.out.println("=========================================");
        //多次分组
        Map<Employee.Status, Map<String, List<Employee>>> collect1 = emp.stream()
                .collect(Collectors.groupingBy(Employee::getStatus, Collectors.groupingBy((str) -> {
                    if (str.getAge() > 50) {
                        return "老年";
                    } else if (str.getAge() > 30) {
                        return "中年";
                    } else {
                        return "青年";
                    }
                })));
        collect1.forEach((k,v)->{
            System.out.println("key:"+k);
            v.forEach((k1,v1)->{
                System.out.println("key1:"+k1);
                v1.forEach(System.out::println);
            });
        });
    }

    @Test
    public void test6(){
        String collect = emp.stream()
                .map(Employee::getName)
                .collect(Collectors.joining(","));
        System.out.println(collect);
    }

    @Test
    public void test7(){
        Map<Boolean, List<Employee>> collect = emp.stream()
                .collect(Collectors.partitioningBy((str) -> str.getAge() > 30));
        collect.forEach((k,v)->{
            System.out.println("key:"+k);
            v.forEach(System.out::println);
        });
    }

    @Test
    public void test8(){
        Optional<Double> collect = emp.stream()
                .map(Employee::getScore)
                .collect(Collectors.reducing(Double::sum));
        System.out.println(collect.get());
        System.out.println("=====================================");
        Integer num = emp.stream()
                .map(Employee::getAge)
                .collect(Collectors.reducing(0,(x, y) -> x + y));
        System.out.println(num);
        System.out.println("=====================================");
        Optional<Double> collect1 = emp.stream()
                .map(Employee::getScore)
                .collect(Collectors.reducing((x, y) -> x + y));
        System.out.println(collect1.get());
    }
    
}
